#ifndef VERIFIER_H
#define VERIFIER_H

#include "trace.h"
#include "sketch.h"

class Verifier{
    public:
        Verifier(){}
        ~Verifier(){}
        
        virtual bool verifySketch(Sketch& sketch){}
        virtual bool verifyTrace(Trace& trace){}
};

class SegmentVerifier : public Verifier{
    public:
        SegmentVerifier(){}
        ~SegmentVerifier(){}
        
        bool verifyTrace(Trace& trace){
            if (trace.size() >= 2){
                float dist = trace[-1].getScenePoint().distance(trace[0].getScenePoint());
                float len = 0;                   
                for (unsigned int i=1; i < trace.size(); i++){
                    len += trace[i-1].getScenePoint().distance(trace[i].getScenePoint());
                }
                if (len < dist * 1.05){
                    return true;
                }
            }
            return false;
        }
};

class  BeautifiedVerifier : public Verifier{
    public:
        BeautifiedVerifier(){}
        ~BeautifiedVerifier(){}
        
        bool verifySketch(Sketch& sketch){
            map<int, Trace>& traces = sketch.getTraces();
            bool beautified = true;
            for (map<int,Trace>::iterator it = traces.begin(); it != traces.end(); it++){
                if (it->second.size() != 2){
                    beautified = false;
                    break;
                }
            }
            return beautified;
        }
};

class  PolygonVerifier : public Verifier{
    private:
        vector<Cursor> vertices;
        vector<Trace> edges;

    public:
        PolygonVerifier(){}
        ~PolygonVerifier(){}
        
        vector<Cursor>& getVertices(){
            return vertices;
        }
        
        vector<Trace>& getEdges(){
            return edges;
        }        
        
        bool verifySketch(Sketch& sketch){
            BeautifiedVerifier beautifiedVerifier;
            
            if ( beautifiedVerifier.verifySketch(sketch) ){
                vertices.clear();
                map<int, Trace>& traces = sketch.getTraces();

                if( traces.size() > 1 ){
                    edges.clear();

                    map<int, Trace>::iterator it;
                    for (it = traces.begin(); it != traces.end(); it++){
                        edges.push_back( traces[it->first] );
                    }
                    
                    for(int i = 0; i < traces.size(); i++){
                        if (edges.size() > 0 and vertices.size() == 0){
                            vertices.push_back(edges[0][0]);
                            vertices.push_back(edges[0][-1]);
                            edges.erase(edges.begin() );
                        }
                        for (int j = 0; j < edges.size(); j++){
                            
                            if (vertices.back().getScenePoint().distance(
                                                    edges[j][0].getScenePoint()) < 0.1){
                                vertices.push_back(edges[j][-1]);
                                edges.erase(edges.begin()+j );
                                break;
                            }
                            if (vertices.back().getScenePoint().distance(
                                                    edges[j][1].getScenePoint()) < 0.1){
                                vertices.push_back(edges[j][0]);
                                edges.erase(edges.begin()+j );
                                break;
                            }
                        }
                        if ( vertices.back().getScenePoint().distance(
                                                 vertices.front().getScenePoint()) < 0.1){
                            return true;
                        }
                    }
                }
            }
            return false;
        }
};

class TapVerifier : public Verifier{
    public:
        TapVerifier(){}
        ~TapVerifier(){}
        
        bool verifyTrace(Trace& trace){
            if (trace.size() < 3){
                return true;
            }
            return false;
        }
};

#endif /* VERIFIER_H */
